home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Sample Code / Snippets / Development Tools & Languages / DTSCPlusLibrary / Sources / FileClass.cp < prev    next >
Encoding:
Text File  |  1993-01-14  |  11.5 KB  |  478 lines  |  [TEXT/MPS ]

  1. /* _________________________________________________________________________________________________________ //
  2.   Copyright © 1992-93 Apple Computer, Inc. All rights reserved.
  3.   Macintosh Developer Technical Support.C++ Macintosh Toolbox Framework.
  4.   Programmer: Kent Sandvik
  5.   Date: 12/27/92
  6.   Revision comments are at the end of this file.
  7.   ---
  8.   TFile is a simple object that does file manipulations    
  9.   TFile.cp contains the TFile class and subclass member functions. 
  10.   _________________________________________________________________________________________________________ */
  11.  
  12. #ifndef _FILECLASS_
  13. #include "FileClass.h"
  14. #endif
  15.  
  16.  
  17. // _________________________________________________________________________________________________________ //
  18. //    TFile
  19. #pragma segment File
  20. TFile::TFile(char* name)
  21. // Create a file object based on the name.
  22. {
  23.     this->Initialize();                            // initialize internal fields to known values
  24.  
  25.     // We are going to assume a lot of things for the default setting
  26.     // and files, for instance that we are creating files in the current working directory (folder)
  27.  
  28.     WDPBRec folderBlock;
  29.     folderBlock.ioNamePtr = nil;
  30.     fError = ::PBHGetVol(&folderBlock, NULL);
  31.     VASSERT(fError == noErr, ("Problems with PBHGetVol = %d", fError));
  32.  
  33.     fFileSpec.vRefNum = folderBlock.ioVRefNum;
  34.     fFileSpec.parID = folderBlock.ioWDDirID;
  35.     c2p(name);
  36.     Pstrcpy(fFileSpec.name, (Str63)name);
  37. }
  38.  
  39.  
  40. #pragma segment File
  41. TFile::TFile(FSSpec theSpec)
  42. // Create a file object based on the FSSpec.
  43. {
  44.     this->Initialize();                            // initialize internal fields to known values
  45.  
  46.     fFileSpec.vRefNum = theSpec.vRefNum;        // store the FSSpec
  47.     fFileSpec.parID = theSpec.parID;
  48.     Pstrcpy(fFileSpec.name, theSpec.name);
  49. }
  50.  
  51.  
  52. #pragma segment File
  53. TFile::TFile(short volume,
  54.              long dirID,
  55.              Str63 name)
  56. // Create a file object based on the volume no, directory ID and the name.
  57. {
  58.     this->Initialize();                            // initialize internal fields to known values
  59.  
  60.     fFileSpec.vRefNum = volume;                    // store values into the FSSpec
  61.     fFileSpec.parID = dirID;
  62.     Pstrcpy(fFileSpec.name, name);
  63. }
  64.  
  65.  
  66. #pragma segment File
  67. TFile::~TFile()
  68. // Default destructor -- empty for the time being.
  69. {
  70. }
  71.  
  72.  
  73. #pragma segment File
  74. void TFile::Initialize()
  75. // Initialize fields to known values.
  76. {
  77.     fFileType = kDefaultType;                    // gee, we assume everyone's reading/writing text files
  78.     fCreator = kDefaultCreator;                    // and who's that?
  79.     fOpened = false;                            // not open yet…
  80.     fFlushing = false;                            // assume things are OK, so we don't flush unless something's critical
  81. }
  82.  
  83.  
  84. // MAIN INTERFACE
  85. #pragma segment File
  86. Boolean TFile::Create()
  87. // Create a new file.
  88. {
  89.     if (!this->FileExists())
  90.     {
  91.         fError = ::HCreate(fFileSpec.vRefNum, fFileSpec.parID, fFileSpec.name, fCreator, fFileType);
  92.         VASSERT(fError == noErr, ("Problems with HCreate = %d\n", fError));
  93.         goto CreateOK;
  94.     }
  95.     return false;
  96. CreateOK:return true;
  97. }
  98.  
  99.  
  100. #pragma segment File
  101. Boolean TFile::Rename(char* newName)
  102. // Rename the file.
  103. {
  104.     if (this->FileExists())
  105.     {
  106.         c2p(newName);
  107.         fError = ::HRename(fFileSpec.vRefNum, fFileSpec.parID, fFileSpec.name, (Str63)newName);
  108.         VASSERT(fError == noErr, ("Problems with HRename = %d", fError));
  109.  
  110.         Pstrcpy(fFileSpec.name, (Str63)newName);
  111.         goto RenameOK;
  112.     }
  113.     return false;
  114. RenameOK:return true;
  115. }
  116.  
  117.  
  118. #pragma segment File
  119. void TFile::Delete()
  120. // Delete the file.
  121. {
  122.     if (fOpened)
  123.         this->Close();                            // first close the file
  124.  
  125.     fError = ::HDelete(fFileSpec.vRefNum, fFileSpec.parID, fFileSpec.name);
  126.     VASSERT(fError == noErr, ("nProblems with HDelete = %d", fError));
  127. }
  128.  
  129.  
  130. #pragma segment File
  131. Boolean TFile::FileExists()
  132. // Test if the file exists or not.
  133. {
  134.     FInfo info;
  135.     fError = HGetFInfo(fFileSpec.vRefNum, fFileSpec.parID, fFileSpec.name, &info);
  136.     return (fError == noErr);
  137. }
  138.  
  139.  
  140. // ACCESSORS AND MUTATORS
  141. #pragma segment File
  142. void TFile::SetType(const OSType creator,
  143.                     const OSType fileType)
  144. // Set file type.
  145. {
  146.     fCreator = creator;
  147.     fFileType = fileType;
  148. }
  149.  
  150.  
  151. #pragma segment File
  152. void TFile::SetFileName(const Str63 fileName)
  153. // Set file name.
  154. {
  155.     Pstrcpy(fFileSpec.name, (StringPtr)fileName);
  156. }
  157.  
  158.  
  159. #pragma segment File
  160. FInfo TFile::GetFileInfo()
  161. // Get FInfo from the specified file.
  162. {
  163.     FInfo info;
  164.     fError = ::HGetFInfo(fFileSpec.vRefNum, fFileSpec.parID, fFileSpec.name, &info);
  165.     VASSERT(fError == noErr, ("Problems with HGetFInfo = %d", fError));
  166.     return info;
  167. }
  168.  
  169.  
  170. // _________________________________________________________________________________________________________ //
  171. //    TDataFile
  172.  
  173. // CONSTRUCTORS AND DESTRUCTORS
  174. #pragma segment File
  175. TDataFile::TDataFile(char* name) :
  176.     TFile(name)
  177. // Default constructor, create a file based on the name.
  178. {
  179. }
  180.  
  181. #pragma segment File
  182. TDataFile::~TDataFile()
  183. // Default destructor -- empty for the time being.
  184. {
  185. }
  186.  
  187.  
  188. // MAIN INTERFACE
  189. #pragma segment File
  190. Boolean TDataFile::Open(SignedByte permission)
  191. // Open a file for data fork only access.
  192. {
  193.     fError = ::HOpen(fFileSpec.vRefNum, fFileSpec.parID, fFileSpec.name, permission, &fRefNum);
  194.     VASSERT(fError == noErr, ("Problems with HOpen = %d", fError));
  195.  
  196.     if (fError == noErr)
  197.         fOpened = true;
  198.     return (fError == noErr);
  199. }
  200.  
  201.  
  202. #pragma segment File
  203. Boolean TDataFile::Close()
  204. // Close the file.
  205. {
  206.     fError = ::FSClose(fRefNum);
  207.     VASSERT(fError == noErr, ("Problems with FSClose = %d", fError));
  208.  
  209.     if (fError == noErr)
  210.         fOpened = false;
  211.  
  212.     if (fFlushing)                                // if flagged, flush the volume
  213.     {
  214.         fError = ::FlushVol(NULL, fFileSpec.vRefNum);
  215.         VASSERT(fError == noErr, ("Problems with FlushVol = %d", fError));
  216.     }
  217.  
  218.     return (fError == noErr);
  219. }
  220.  
  221.  
  222. #pragma segment File
  223. Boolean TDataFile::WriteHandle(Handle h)
  224. // Write a handle to file (the whole handle).
  225. {
  226.     long len = ::GetHandleSize(h);                // get lenght of handle
  227.  
  228.     fError = ::SetFPos(fRefNum, fsFromStart, kNoOffset);// move pointer to beginning of file
  229.     VASSERT(fError == noErr, ("Problems with SetFPos = %d", fError));
  230.  
  231.     fError = ::FSWrite(fRefNum, &len, *h);        // write the handle to disk
  232.     VASSERT(fError == noErr, ("Problems with FSWrite = %d", fError));
  233.  
  234.     fError = ::SetEOF(fRefNum, len);            // change size of file if needed
  235.     VASSERT(fError == noErr, ("Problems with SetEOF = %d", fError));
  236.  
  237.     if (fFlushing)
  238.     {
  239.         fError = ::FlushVol(NULL, fFileSpec.vRefNum);
  240.         VASSERT(fError == noErr, ("Problems with FlushVol = %d", fError));
  241.     }
  242.     return (fError == noErr);
  243. }
  244.  
  245.  
  246. #pragma segment File
  247. Handle TDataFile::ReadHandle()
  248. // Read handle from the file (the whole handle).
  249. {
  250.     Handle h = NULL;
  251.     long len;
  252.  
  253.     fError = ::GetEOF(fRefNum, &len);            // get size of handle in file
  254.     VASSERT(fError == noErr, ("Problems with GetEOF = %d", fError));
  255.  
  256.     h = ::NewHandle(len);                        // create a new handle
  257.     if (h == NULL)                                // problems creating a handle 
  258.     {
  259.         ASSERT(fError == noErr, "\pProblems with NewHandle");
  260.         goto ReadHandleFalse;
  261.     }
  262.  
  263.     fError = ::SetFPos(fRefNum, fsFromStart, kNoOffset);
  264.     VASSERT(fError == noErr, ("Problems with SetFPos = %d", fError));
  265.  
  266.     fError = ::FSRead(fRefNum, &len, *h);        // read into handle
  267.     VASSERT(fError == noErr, ("Problems with SetFPos = %d", fError));
  268.  
  269.     return h;
  270. ReadHandleFalse:return NULL;
  271. }
  272.  
  273.  
  274. #pragma segment File
  275. Boolean TDataFile::Write(Ptr buffer,
  276.                          long bytes)
  277. // Write N bytes from buffer to file.
  278. {
  279.     fError = ::FSWrite(fRefNum, &bytes, buffer);
  280.     VASSERT(fError == noErr, ("Problems with FSWrite = %d", fError));
  281.     return (fError == noErr);
  282. }
  283.  
  284.  
  285. #pragma segment File
  286. Boolean TDataFile::Read(Ptr buffer,
  287.                         long bytes)
  288. // Read N bytes from file to buffer.
  289. {
  290.     fError = ::FSRead(fRefNum, &bytes, buffer);
  291.     VASSERT(fError == noErr, ("Problems with FSWrite = %d", fError));
  292.     return (fError == noErr);
  293. }
  294.  
  295.  
  296. #pragma segment File
  297. Boolean TDataFile::SetMark(short from,
  298.                            long offset)
  299. // Set file mark (beginning, end, offset).
  300. {
  301.     if (fOpened)                                // have an open file?
  302.     {
  303.         fError = ::SetFPos(fRefNum, from, offset);
  304.         VASSERT(fError == noErr, ("Problems with SetFPos = %d", fError));
  305.         goto SetMarkOK;
  306.     }
  307.     else
  308.         return false;
  309. SetMarkOK:return (fError == noErr);
  310. }
  311.  
  312.  
  313. #pragma segment File
  314. long TDataFile::GetMark()
  315. // Get file mark (offset).
  316. {
  317.     long offset = 0;
  318.  
  319.     fError = ::GetFPos(fRefNum, &offset);
  320.     VASSERT(fError == noErr, ("Problems with GetFPos = %d", fError));
  321.  
  322.     return offset;
  323. }
  324.  
  325.  
  326. #pragma segment File
  327. Boolean TDataFile::Reset()
  328. // Set file mark to beginning of file.
  329. {
  330.     return (this->SetMark(fsFromStart, kNoOffset));// set mark to beginning of file
  331. }
  332.  
  333.  
  334. #pragma segment File
  335. Boolean TDataFile::GotoEndOfFile()
  336. // Set file mark to end of file.
  337. {
  338.     return (this->SetMark(fsFromLEOF, kNoOffset));// set mark to end of file
  339. }
  340.  
  341.  
  342. // _________________________________________________________________________________________________________ //
  343. //    TResourceFile
  344. // CONSTRUCTORS AND DESTRUCTORS
  345. #pragma segment File
  346. TResourceFile::TResourceFile(char* name) :
  347.     TFile(name)
  348. // Default destructor, create a TResourceFile object.
  349. {
  350. }
  351.  
  352.  
  353. #pragma segment File
  354. TResourceFile::~TResourceFile()
  355. // Default destructor -- not used for the time being.
  356. {
  357. }
  358.  
  359.  
  360. // MAIN INTERFACE
  361. #pragma segment File
  362. Boolean TResourceFile::Create()
  363. // Create the actual resource file.
  364. {
  365.     if (!this->FileExists())
  366.     {
  367.         Boolean result = TFile::Create();        // call inherited create
  368.         if (result)                                // if OK
  369.         {
  370.             ::HCreateResFile(fFileSpec.vRefNum, fFileSpec.parID, fFileSpec.name);
  371.             goto CreateResourceOK;
  372.         }
  373.         else
  374.             goto CreateResourceFalse;            // result = false
  375.     }
  376.     else
  377.         goto CreateResourceFalse;                // couldn't create a file that exists
  378.  
  379. CreateResourceFalse:return false;
  380. CreateResourceOK:if (ResError() == noErr)
  381.         return true;
  382.     else
  383.         return false;
  384. }
  385.  
  386.  
  387. #pragma segment File
  388. Boolean TResourceFile::Open(SignedByte permission)
  389. // Open the resource file.
  390. {
  391.     if (fOpened)
  392.     {
  393.         fRefNum = ::HOpenResFile(fFileSpec.vRefNum, fFileSpec.parID, fFileSpec.name, permission);
  394.         VASSERT(fRefNum != -1, ("Problems with HOpenResFile = %d", ::ResError()));
  395.         if (::ResError() == 0)
  396.             goto ResourceFileOpenOK;
  397.         else
  398.             goto ResourceFileOpenFalse;
  399.     }
  400.     else
  401.         goto ResourceFileOpenFalse;                // can't open an already open file
  402. ResourceFileOpenFalse:return false;
  403. ResourceFileOpenOK:fOpened = true;
  404.     return true;
  405. }
  406.  
  407.  
  408. #pragma segment File
  409. Boolean TResourceFile::Close()
  410. // Close the resource file.
  411. {
  412.     if (fOpened)
  413.     {
  414.         ::CloseResFile(fRefNum);
  415.         VASSERT(fRefNum != -1, ("Problems with CloseResFile = %d", ::ResError()));
  416.         if (::ResError() == 0)
  417.             goto ResourceFileCloseOK;
  418.         else
  419.             goto ResourceFileCloseFalse;
  420.     }
  421. ResourceFileCloseFalse:return false;
  422. ResourceFileCloseOK:fRefNum = 0;
  423.     fOpened = false;
  424.     return true;
  425. }
  426.  
  427.  
  428. #pragma segment File
  429. Boolean TResourceFile::HasResourceFork()
  430. // Check if the supposed resource file actually has a resource fork.
  431. {
  432.     HFileParam pb;
  433.  
  434.     pb.ioNamePtr = fFileSpec.name;                // get the name
  435.     pb.ioVRefNum = fFileSpec.vRefNum;            // and the volume
  436.     pb.ioDirID = fFileSpec.parID;                // and the DirID
  437.     pb.ioFDirIndex = 0;                            // zero this one
  438.  
  439.     fError = ::PBHGetFInfo((HParmBlkPtr) & pb, false);// call the right trap
  440.     VASSERT(fError == noErr, ("Problems with PBHGetFInfo = %d", fError));
  441.  
  442.     return (pb.ioFlRLgLen != 0);                // if the resource fork is non-zero, then we got one
  443. }
  444.  
  445.  
  446. #pragma segment File
  447. void TResourceFile::Update()
  448. // Update the resource file.
  449. {
  450.     if (fOpened)
  451.     {
  452.         ::UpdateResFile(fRefNum);
  453.         VASSERT(::ResError() == noErr, ("Problems with UpdateResFile = %d", ::ResError()));
  454.         if (fFlushing)
  455.         {
  456.             fError = ::FlushVol(NULL, fFileSpec.vRefNum);
  457.             VASSERT(fError == noErr, ("Problems with FlushVol = %d", fError));
  458.         }
  459.     }
  460. }
  461.  
  462.  
  463. #pragma segment File
  464. void TResourceFile::Assign()
  465. // Make sure that we are using this specified resource file.
  466. {
  467.     if (fOpened)
  468.         ::UseResFile(fRefNum);
  469. }
  470.  
  471.  
  472. // _________________________________________________________________________________________________________ //
  473. /*    Change History (most recent last):
  474.   No        Init.    Date        Comment
  475.   1            khs        12/27/92    New file
  476.   2            khs        1/14/93        Cleanup
  477. */
  478.